'use strict';
// Copyright 2014 Blueant Inc. All Rights Reserved.

/**
 * @fileoverview 背包
 * @author sundbcn@gmail.com (sun debing)
 */

var mongoose = require('mongoose');
var _ = require('lodash');
var bagGemstoneSchema = require('./bag/bagGemstoneSchema');
var bagEquipSchema = require('./bag/bagEquipSchema');
var bagPropertySchema = require('./bag/bagPropertySchema');
var bagConsumeSchema = require('./bag/bagConsumeSchema');
var itemUtil = require('../util/itemUtil');
var genEquipService = require('../services/genEquipService');
var propertyConf = require('../config/propertyConf');
var consumeConf = require('../config/consumeConf');
var equipConf = require('../config/equipConf');
var constantUtil = require('../util/constantUtil');
var equipPartType = require('../consts/equipPartType');
var dataApi = require('../libs/dataApi');
var bagMgr = require('../mgr/bagMgr');

/**
 * 背包
 */
var bagSchema = new mongoose.Schema({
    // 角色id
    role_id: {
        type: Number,
        required: true,
        unique: true,
        index: true
    },

    // 装备列表
    equip_list: [bagEquipSchema],

    // 材料列表
    property_list: [bagPropertySchema],

    // 消耗品列表
    consume_list: [bagConsumeSchema],

    // 穿上的装备列表
    wear_equip_list: {
        // 武器
        weapon: {
            type: Number
        },

        // 头
        head: {
            type: Number
        },

        // 肩膀
        shoulder: {
            type: Number
        },

        // 护甲
        armor: {
            type: Number
        },

        // 左戒指
        ring: {
            type: Number
        },

        // 右戒指
        ear_ring: {
            type: Number
        }
    },

    // 自增id
    max_id: {
        type: Number,
        default: 10000
    }
});

bagSchema.pre('save', function (next) {
    this.increment();
    if (!this.isNew && !!this.isModified()) {
        this.pushModify();
    }
    next();
});

/**
 * 获取消耗品列表
 */

bagSchema.methods.getConsumeList = function () {
    return this.consume_list;
};

/**
 * 获取消耗品
 */
bagSchema.methods.getConsume = function (consume_id) {
    for (var i = 0; i < this.consume_list.length; i++) {
        var consume_item = this.consume_list[i];
        if (consume_item.getId() == consume_id) {
            return consume_item;
        }
    }
    return null;
};

/**
 * 添加消耗品
 */
bagSchema.methods.addConsume = function (consume_type, num) {
    num = num || 1;
    if (!consumeConf.getConsumeTypeConf(consume_type)) {
        return false;
    }
    for (var i = 0; i < this.consume_list.length; i++) {
        var consume = this.consume_list[i];

        // 判断最大可叠加的个数
        if (consume.getType() == consume_type) {
            consume.stack_num += num;
            return true;
        }
    }

    this.consume_list.push({
        consume_id: this.genId(),
        consume_type: consume_type,
        stack_num: num
    });
    return true;
};

/**
 * 删除消耗品一组
 * @param  {[type]} consume_type [description]
 * @return {[type]}               [description]
 */
bagSchema.methods.removeConsume = function (consume_id) {
    var consume_item = this.getConsume(consume_id);
    if (!consume_item) {
        return false;
    }
    consume_item.remove();
    this.remove_consume_list = this.remove_consume_list || [];
    this.remove_consume_list.push({
        consume_id: consume_id,
        del: 1
    });
    return true;
};

/**
 * 删除消耗品单个
 * @param  {[type]} consume_type [description]
 * @return {[type]}               [description]
 */
bagSchema.methods.subConsume = function (consume_type) {
    var self = this;
    var remove_consume = null;
    _.some(this.consume_list, function (consume_item) {
        if (consume_item.getType() == consume_type &&
            consume_item.getStackNum() > 0
        ) {
            consume_item.subStackNum();
            remove_consume = consume_item;
            if (consume_item.getStackNum() <= 0) {
                self.removeConsume(consume_item.getId());
            }
            return true;
        }
    });

    return remove_consume;
};

/**
 * 添加材料
 */
bagSchema.methods.addProperty = function (property_type, num) {
    num = num || 1;
    if (!propertyConf.getPropertyTypeConf(property_type)) {
        return false;
    }
    for (var i = 0; i < this.property_list.length; i++) {
        var property = this.property_list[i];

        // 判断最大可叠加的个数
        if (property.getType() == property_type) {
            property.stack_num += num;
            return true;
        }
    }

    this.property_list.push({
        property_id: this.genId(),
        property_type: property_type,
        stack_num: num
    });
    return true;
};

/**
 * 删除道具
 * @param  {[type]} property_type [description]
 * @return {[type]}               [description]
 */
bagSchema.methods.removeProperty = function (property_id) {
    var property_item = this.getProperty(property_id);
    if (!property_item) {
        return false;
    }
    this.remove_property_list = this.remove_property_list || [];
    this.remove_property_list.push({
        property_id: property_id,
        del: 1
    });
    property_item.remove();
    // this.property_list.pull(property_item);

    return true;
};

/**
 * 删除道具
 */
bagSchema.methods.subProperty = function (property_type, sub_num) {
    var self = this;
    sub_num = sub_num || 1;
    var is_valid = false;
    _.some(this.property_list, function (property_item) {
        if (property_item.getType() === property_type) {
            var stack_num = property_item.getStackNum();
            if (stack_num <= sub_num) {
                // 当前项不足或刚刚好够，则消耗掉当前项，并清除当前堆
                property_item.subStackNum(stack_num);
                self.removeProperty(property_item.getId());
                if (stack_num == sub_num) {
                    // 当前材料刚好够用
                    is_valid = true;
                }
            } else {
                // 当前项材料充足
                property_item.subStackNum(sub_num);
                is_valid = true;
            }
            return true;
        }
        return false;
    });
    return is_valid;
};

/**
 * 获取材料列表
 */
bagSchema.methods.getPropertyList = function () {
    return this.property_list;
};

/**
 * 获取材料
 */
bagSchema.methods.getProperty = function (property_id) {
    for (var i = 0; i < this.property_list.length; i++) {
        var property_item = this.property_list[i];
        if (property_item.getId() == property_id) {
            return property_item;
        }
    }
    return null;
};

bagSchema.methods.addEquip = function (equip_type) {
    return this.addEquipWithAttrAndHole(equip_type, 0, 0);
};

/**
 * 添加装备
 */
bagSchema.methods.addEquipWithAttrAndHole = function (
    equip_type,
    hole_num,
    lv) {
    var gen_equip = genEquipService.generateEquip(equip_type);
    if (!gen_equip) {
        return false;
    }
    gen_equip.lv = lv;
    if (!gen_equip) {
        return false;
    }
    return this.addEquipByGen(gen_equip);
};

/**
 * 添加已经生成好的装备
 * @param {[type]}  equip_type [description]
 */
bagSchema.methods.addEquipByGen = function (gen_equip) {
    gen_equip.equip_id = this.genId();
    this.equip_list.push(gen_equip);
    return gen_equip;
};

/**
 * 移除装备
 * @param  {[type]} equip_id [description]
 * @return {[type]}          [description]
 */
bagSchema.methods.removeEquip = function (equip_id) {
    var equip_item = this.getEquip(equip_id);
    if (!equip_item) {
        return false;
    }
    equip_item.remove();
    this.remove_equip_list = this.remove_equip_list || [];
    this.remove_equip_list.push({
        equip_id: equip_id,
        del: 1
    });
    return true;
};

/**
 * 获取装备
 * @param  {[type]} item_id [description]
 * @return {[type]}         [description]
 */
bagSchema.methods.getEquip = function (equip_id) {
    for (var i = 0; i < this.equip_list.length; i++) {
        var equip_item = this.equip_list[i];
        if (equip_item.getId() == equip_id) {
            return equip_item;
        }
    }
    return null;
};

/**
 * 是否已经被装备
 * @param  {[type]} equip_id [description]
 * @return {[type]}         [description]
 */
bagSchema.methods.isEquip = function (equip_id) {
    var is_equip = false;
    _.some(this.wear_equip_list, function (wear_equip_id) {
        if (equip_id == wear_equip_id) {
            is_equip = true;
            return true;
        }
    });
    return is_equip;
};

/**
 * 获取装备列表
 * @return {[type]}         [description]
 */
bagSchema.methods.getEquipList = function () {
    return this.equip_list;
};

/**
 * 判断是否属性优于其他装备
 * @param  {[type]}  equip_item [description]
 * @return {Boolean}            [description]
 */
bagSchema.methods.getBestEquipIdByPart = function (job_type, equip_part) {
    var equip_list = this.getEquipList();
    var last_quality = 0;
    var last_property_value = 0;
    var find_equip_item;

    var getEquipPropertyValue = function (equip_item) {
        var equip_type_conf = dataApi.equipment_type.findById(equip_item.equip_type);
        var strength_lv_conf = dataApi.equipment_strengthen.findById(equip_item.lv);
        var equip_lv_conf = dataApi.equipment_lvl.findById(equip_item.refine_lv);
        var equip_lv_add_per = equip_lv_conf ? equip_lv_conf.add_per : 0;
        var equip_refine_lv_add_per = strength_lv_conf ? strength_lv_conf.value : 0;
        var property_value = equip_type_conf.value;
        property_value *= (1 + equip_refine_lv_add_per / 100) * (1 + equip_lv_add_per / 100);
        return property_value;
    };

    _.each(equip_list, function (equip_item) {
        var equip_part_type = itemUtil.getEquipPartType(equip_item.getType());
        var equip_conf = equipConf.getEquipTypeConf(equip_item.equip_type);
        if (equip_part_type != equip_part) {
            return;
        }

        if (job_type != equip_conf.profession && equip_conf.profession !== 0) {
            return;
        }

        if (equip_conf.quality > last_quality) {
            find_equip_item = equip_item;
            last_quality = equip_conf.quality;
            return;
        } else if (equip_conf.quality < last_quality) {
            return;
        }

        var property_value = getEquipPropertyValue(equip_item);
        if (property_value > last_property_value) {
            find_equip_item = equip_item;
            last_property_value = property_value;
            return;
        }
    });
    if (!!find_equip_item) {
        return find_equip_item.equip_id;
    }
    return 0;
};

/**
 * 获取装备列表
 * @return {[type]}         [description]
 */
bagSchema.methods.getWearEquipList = function () {
    var self = this;
    var equip_item_list = [];
    _.each(self.wear_equip_list, function (equip_id) {
        var equip_item = self.getEquip(equip_id);
        if (!!equip_item) {
            equip_item_list.push(equip_item);
        }
    });
    return equip_item_list;
};

/**
 * 穿上装备
 * @param  {[type]} item_id [description]
 * @return {[type]}         [description]
 */
bagSchema.methods.equip = function (equip_id) {
    var equip = this.getEquip(equip_id);
    if (!equip) {
        return false;
    }

    var equip_part_type = itemUtil.getEquipPartType(equip.getType());
    switch (equip_part_type) {
    case equipPartType.WEAPON:
        {
            this.wear_equip_list.weapon = equip_id;
            break;
        }

    case equipPartType.HEAD:
        {
            this.wear_equip_list.head = equip_id;
            break;
        }

    case equipPartType.SHOULDER:
        {
            this.wear_equip_list.shoulder = equip_id;
            break;
        }

    case equipPartType.ARMOR:
        {
            this.wear_equip_list.armor = equip_id;
            break;
        }

    case equipPartType.RING:
        {
            this.wear_equip_list.ring = equip_id;
            break;
        }

    case equipPartType.EAR_RING:
        {
            this.wear_equip_list.ear_ring = equip_id;
            break;
        }
    }
    this.markModified('wear_equip_list');
    return true;
};

bagSchema.methods.equipOnekey = function (job_type) {
    this.equip(this.getBestEquipIdByPart(job_type, equipPartType.WEAPON));
    this.equip(this.getBestEquipIdByPart(job_type, equipPartType.HEAD));
    this.equip(this.getBestEquipIdByPart(job_type, equipPartType.SHOULDER));
    this.equip(this.getBestEquipIdByPart(job_type, equipPartType.ARMOR));
    this.equip(this.getBestEquipIdByPart(job_type, equipPartType.RING));
    this.equip(this.getBestEquipIdByPart(job_type, equipPartType.EAR_RING));
    this.markModified('wear_equip_list');
};

bagSchema.methods.genId = function () {
    this.max_id++;
    return this.max_id;
};

/**
 * 获取修改
 * @return {[type]} [description]
 */
bagSchema.methods.getLastChange = function () {
    var equip_list = [];
    var property_list = [];
    var consume_list = [];

    // 消耗品
    _.each(this.consume_list, function (consume_item) {
        if (!!consume_item.isModified()) {
            consume_list.push(consume_item);
        }
    });

    _.each(this.remove_consume_list, function (remove_consume_item) {
        consume_list.push(remove_consume_item);
    });
    this.remove_consume_list = [];

    // 装备
    _.each(this.equip_list, function (equip_item) {
        if (!!equip_item.isModified()) {
            equip_list.push(equip_item);
        }
    });

    _.each(this.remove_equip_list, function (remove_equip_item) {
        equip_list.push(remove_equip_item);
    });
    this.remove_equip_list = [];

    // 道具
    _.each(this.property_list, function (property_item) {
        if (!!property_item.isModified()) {
            property_list.push(property_item);
        }
    });

    _.each(this.remove_property_list, function (remove_property_item) {
        property_list.push(remove_property_item);
    });
    this.remove_property_list = [];

    return {
        equip_list: equip_list,
        property_list: property_list,
        consume_list: consume_list,
        wear_equip_list: this.wear_equip_list
    };
};

/**
 * 推送
 * @return {[type]} [description]
 */
bagSchema.methods.push = function () {
    bagMgr.sendBagChanged(
        this.role_id,
        this.toJSON(),
        function (err, fails) {
            if (err) {
                console.error('send bag message error: %j, fail ids: %j', err, fails);
                return;
            }
        });
};

bagSchema.methods.pushModify = function () {
    bagMgr.sendBagChanged(
        this.role_id,
        this.getLastChange(),
        function (err, fails) {
            if (err) {
                console.error('send bag message error: %j, fail ids: %j', err, fails);
                return;
            }
        });
};

if (!bagSchema.options.toJSON) {
    bagSchema.options.toJSON = {};
}
/* jshint unused:false */
bagSchema.options.toJSON.transform = function (doc, ret) {
    delete ret.role_id;
    delete ret._id;
};

mongoose.model('Bag', bagSchema);
